package com.lucker.common.util;

import java.io.IOException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

import javax.crypto.Cipher;

import com.alibaba.fastjson.JSONObject;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;



public class RSAUtil {

	
	
	//生成秘钥对
		public static KeyPair getKeyPair() throws Exception {
			KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
			keyPairGenerator.initialize(2048);
			KeyPair keyPair = keyPairGenerator.generateKeyPair();
			return keyPair;
		}
		
		//获取公钥(Base64编码)
		public static String getPublicKey(KeyPair keyPair){
			PublicKey publicKey = keyPair.getPublic();
			byte[] bytes = publicKey.getEncoded();
			return byte2Base64(bytes);
		}
		
		//获取私钥(Base64编码)
		public static String getPrivateKey(KeyPair keyPair){
			PrivateKey privateKey = keyPair.getPrivate();
			byte[] bytes = privateKey.getEncoded();
			return byte2Base64(bytes);
		}
		
		//将Base64编码后的公钥转换成PublicKey对象
		public static PublicKey string2PublicKey(String pubStr) throws Exception{
			byte[] keyBytes = base642Byte(pubStr);
			X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
			KeyFactory keyFactory = KeyFactory.getInstance("RSA");
			PublicKey publicKey = keyFactory.generatePublic(keySpec);
			return publicKey;
		}
		
		//将Base64编码后的私钥转换成PrivateKey对象
		public static PrivateKey string2PrivateKey(String priStr) throws Exception{
			byte[] keyBytes = base642Byte(priStr);
			PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
			KeyFactory keyFactory = KeyFactory.getInstance("RSA");
			PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
			return privateKey;
		}
		
		//公钥加密
		public static byte[] publicEncrypt(byte[] content, PublicKey publicKey) throws Exception{
			Cipher cipher = Cipher.getInstance("RSA");
			cipher.init(Cipher.ENCRYPT_MODE, publicKey);
			byte[] bytes = cipher.doFinal(content);
			return bytes;
		}
		
		//私钥解密
		public static byte[] privateDecrypt(byte[] content, PrivateKey privateKey) throws Exception{
			Cipher cipher = Cipher.getInstance("RSA");
			cipher.init(Cipher.DECRYPT_MODE, privateKey);
			byte[] bytes = cipher.doFinal(content);
			return bytes;
		}
		
		//字节数组转Base64编码
		public static String byte2Base64(byte[] bytes){
			BASE64Encoder encoder = new BASE64Encoder();
			return encoder.encode(bytes);
			
		}
		
		//Base64编码转字节数组
		public static byte[] base642Byte(String base64Key) throws IOException{
			BASE64Decoder decoder = new BASE64Decoder();
			return decoder.decodeBuffer(base64Key);
		}
		
		
		
		
		
		
		public static void main(String[] args) {
			
			
			rsaTest();
			
			
			
			
		}
		
		public static void rsaTest() {
			
			String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrN8d/1NwLqyQkolhItI8sR9Ts\r\n" + 
					"I1UzKEISkDfoSBPnr+LcWlogXaivNeivwNekqfRdZagfAAOHe+rqQh3C5N0lteSJ\r\n" + 
					"0A1homRk/TExPE4lgMiiV5T64SYlX7v/ovyOeVDZqQfp6/tzzrL/YDTQR5aURcas\r\n" + 
					"1WOoNrbptx/Dgno4QwIDAQAB";
			
			
			
			String privateKey = "MIICxjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIhPhXURgQElUCAggA\r\n" + 
					"MBQGCCqGSIb3DQMHBAgsAtmobPTkeQSCAoC6Fvjg2gea6uD/sIBGt1W8zihYTd+e\r\n" + 
					"lW1Tfgt9YEwwP+Qb6oBDntFnsxT1U5vDFyUhz6hW8fCYvGfSaxnJn41sMGTK8PtP\r\n" + 
					"YTXuLVw261WQREYN7Yf/FCPA73lflD/fF/VSCTDVmyygaiJVpK/00pbPFtkfBBnW\r\n" + 
					"9xYMZqToNL0nwkIGtT/1Eya2yCpISLBnerKJuQqVXMYDfc8k5EjgiR5c0FAMzqbe\r\n" + 
					"QS6aIQOFqaCfgK/6QMbj64hXeRoQqnqkIOtLGe07/+74BjONewR+7AApVtCFqCQl\r\n" + 
					"EzeGw7rWQjjVMH2OPNI8vQBoJJSrdU2T3JMmUPLKlvFdzmMweF4D3FZKRVy1EJ15\r\n" + 
					"OZs0sZXkGb86ELHPW4ACosk+adv1WQE/yHAKED5OfhwZ+J+bUTzbO0vWqcRrOOGm\r\n" + 
					"C3Gdoal+hGTZaNJXAdl2oYShwhUqjwzl/Lw9pQC1ZZ/yswpIRxd5PY+g53eY+T8/\r\n" + 
					"q4hk1RSbrhjFrJNd3Z2Q2XAisRJ1sNyTdDo2cd5vxXnF/ymlOhghAT+YX9J1YOYO\r\n" + 
					"f9AV9jhy6WBq991jTATt1A7n1dM/CMUAgktbOGadDD8RHIeIKzvf0tvom6IyTJvw\r\n" + 
					"lZNyCH1Agw42vicImgFpUaHZOobNzpKjoo8vrxbZLHK/0IYBWD/loGitSMfg+OlS\r\n" + 
					"wXNgpldtUd02jtG1muRZK5fiHt7qHHwGQA77AmocNnxF8NM3ykGJc0maUe779DbV\r\n" + 
					"/M9mhaxYltINTbPtMyGZUoZMzpsbKiB9ss5MdzAxXqa48lyjfpDfq4yrCeSsMwBb\r\n" + 
					"3APqldCjIh7+Q4EX96/tAcLcVVmKVbM3wIdme2FSq1ECHAM4Y2rfjIkQ";
			
			try {
				String publicKeyStr = byte2Base64(publicKey.getBytes());
				String privateKeyStr = byte2Base64(privateKey.getBytes());
				//System.out.println("RSA公钥Base64编码:" + publicKeyStr);
				//System.out.println("RSA私钥Base64编码:" + privateKeyStr);
				
				
				Map<String,Object> msgMap = new HashMap<String,Object>();
				msgMap.put("caiId", 101);
				msgMap.put("userId", 222);
				
				String message = JSONObject.toJSONString(msgMap);
				
				
				//将Base64编码后的公钥转换成PublicKey对象
				PublicKey publicKeyss = RSAUtil.string2PublicKey(publicKeyStr);
				//用公钥加密
				byte[] publicEncrypt = RSAUtil.publicEncrypt(message.getBytes(), publicKeyss);
				//加密后的内容Base64编码
				String byte2Base64 = RSAUtil.byte2Base64(publicEncrypt);
				System.out.println("公钥加密并Base64编码的结果：" + byte2Base64);
				
				
				
			}catch (Exception e) {
				e.printStackTrace();
				
				
			}
		}
		
		public static void testRSA(){
			
			try {
				
				//===============生成公钥和私钥，公钥传给客户端，私钥服务端保留==================
				//生成RSA公钥和私钥，并Base64编码
				KeyPair keyPair = RSAUtil.getKeyPair();
				String publicKeyStr = RSAUtil.getPublicKey(keyPair);
				String privateKeyStr = RSAUtil.getPrivateKey(keyPair);
				System.out.println("RSA公钥Base64编码:" + publicKeyStr);
				System.out.println("RSA私钥Base64编码:" + privateKeyStr);
				
				//=================客户端=================
				//hello, i am infi, good night!加密
				String message = "hello, i am infi, good night!";
				//将Base64编码后的公钥转换成PublicKey对象
				PublicKey publicKey = RSAUtil.string2PublicKey(publicKeyStr);
				//用公钥加密
				byte[] publicEncrypt = RSAUtil.publicEncrypt(message.getBytes(), publicKey);
				//加密后的内容Base64编码
				String byte2Base64 = RSAUtil.byte2Base64(publicEncrypt);
				System.out.println("公钥加密并Base64编码的结果：" + byte2Base64);
				
				
				//##############	网络上传输的内容有Base64编码后的公钥 和 Base64编码后的公钥加密的内容     #################
				
				
				
				//===================服务端================
				//将Base64编码后的私钥转换成PrivateKey对象
				PrivateKey privateKey = RSAUtil.string2PrivateKey(privateKeyStr);
				//加密后的内容Base64解码
				byte[] base642Byte = RSAUtil.base642Byte(byte2Base64);
				//用私钥解密
				byte[] privateDecrypt = RSAUtil.privateDecrypt(base642Byte, privateKey);
				//解密后的明文
				System.out.println("解密后的明文: " + new String(privateDecrypt));
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	
}
